//
// Created by LiuYou on 2021/8/17.
//

#include <cstring>
#include <cstdio>
#include "TimerLinkedList.hpp"

ClientData::ClientData(const sockaddr_in& clientAddress, int socketFd, char* buf, UtilityTimer* utilityTimer) :
        clientAddress( clientAddress ),
        socketFd( socketFd ),
        buf(),
        utilityTimer( utilityTimer ) {
    strcpy( this->buf, buf );
}

ClientData::ClientData() :
        clientAddress(),
        socketFd(),
        buf(),
        utilityTimer() {}

ClientData::~ClientData() = default;

UtilityTimer::UtilityTimer(time_t expire, void (* cbFunc)(ClientData*), ClientData* clientData, UtilityTimer* prev,
                           UtilityTimer* next) :
        expire( expire ),
        cb_func( cbFunc ),
        clientData( clientData ),
        prev( prev ),
        next( next ) {}

UtilityTimer::UtilityTimer() :
        expire(),
        cb_func(),
        clientData(),
        prev(),
        next() {}

UtilityTimer::~UtilityTimer() = default;

TimerLinkedList::TimerLinkedList(UtilityTimer* head, UtilityTimer* tail) : head( head ), tail( tail ) {}

TimerLinkedList::TimerLinkedList() : head( nullptr ), tail( nullptr ) {}

TimerLinkedList::~TimerLinkedList() {
    UtilityTimer* tmp = head;
    while (tmp) {
        head = tmp->next;
        delete tmp;
        tmp = head;
    }
}

void TimerLinkedList::addTimer(UtilityTimer* timer) {
    if (!timer) {
        return;
    }
    if (!head) {
        head = timer;
        tail = timer;
        return;
    }
    if (timer->expire < head->expire) {
        timer->next = head;
        head->prev = timer;
        head = timer;
        return;
    }
    addTimer( timer, head );
}

void TimerLinkedList::adjustTimer(UtilityTimer* timer) {
    if (!timer) {
        return;
    }
    UtilityTimer* tmp = timer->next;
    if (!tmp || (timer->expire < tmp->expire)) {
        return;
    }
    if (timer == head) {
        head = head->next;
        head->prev = nullptr;
        timer->next = nullptr;
        addTimer( timer, head );
    } else {
        timer->prev->next = timer->next;
        timer->next->prev = timer->prev;
        addTimer( timer, timer->next );
    }
}

void TimerLinkedList::deleteTimer(UtilityTimer* timer) {
    if (!timer) {
        return;
    }
    if ((timer == head) && (timer == tail)) {
        delete timer;
        head = nullptr;
        tail = nullptr;
        return;
    }
    if (timer == head) {
        head = head->next;
        head->prev = nullptr;
        delete timer;
        return;
    }
    if (timer == tail) {
        tail = tail->prev;
        tail->next = nullptr;
        delete timer;
        return;
    }
    timer->prev->next = timer->next;
    timer->next->prev = timer->prev;
    delete timer;
}

void TimerLinkedList::tick() {
    if (!head) {
        return;
    }
    printf( "timer tick(定时器滴答, 定时器打√, 定时器封装的定时事件任务到期了。)\n" );
    time_t currentTime = time( nullptr );
    UtilityTimer* tmp = head;
    while (tmp) {
        if (currentTime < tmp->expire) {
            break;
        }
        tmp->cb_func( tmp->clientData );
        head = tmp->next;
        if (head) {
            head->prev = nullptr;
        }
        delete tmp;
        tmp = head;
    }
}

void TimerLinkedList::addTimer(UtilityTimer* timer, UtilityTimer* headNode) {
    UtilityTimer* prev = headNode;
    UtilityTimer* tmp = prev->next;

    while (tmp) {
        if (timer->expire < tmp->expire) {
            prev->next = timer;
            timer->next = tmp;
            tmp->prev = timer;
            timer->prev = prev;
            break;
        }
        prev = tmp;
        tmp = tmp->next;
    }
    if (!tmp) {
        prev->next = timer;
        timer->prev = prev;
        timer->next = nullptr;
        tail = timer;
    }
}
